﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml.Linq;

using Perseus;
using Perseus.Plugins;

using Hetymine.Executioner.Commands;

namespace Hetymine.Executioner.Plugins.Lua {
    public class Lua : CommandPlugin, IExecutableCommands, ILoader {        
        public Lua() {
            this.PluginInfo = PluginInfo.FromAssembly(this.GetType().Assembly, "Blake Hancock");
        }

        public override ICommand InitializeCommand() {
            return new LuaCommand(this);
        }

        #region Registered Functions
        public void LuaDisplay(string text, int time) {
            Display d = new Display();
            d.Text = text;
            time = time.MaxMin(500, 10000);
            d.Time = time;
            d.Show();
        }
        #endregion

        public Perseus.Scripting.Lua.Lua Interface { get; set; }

        #region IExecutableCommand Members
        public List<string> Names { get; protected set; }
        public bool ExecuteCommand(string command, string parameters) {
            bool result = false;
                        
            if (this.InitializeScript(command)) {                
                result = (bool)this.Interface.CallFunction(command + ".execute", parameters);                
            }
            
            return result;
        }
        #endregion

        public bool InitializeScript(string name) {
            if (!this.IsValidLuaScriptName(name)) {
                return false;
            }

            // Load scripts on demmand
            if (this.Names.Contains(name) && !this.Interface.IsSet(name)) {                
                string script = AppDomain.CurrentDomain.BaseDirectory + "scripts" +
                    Path.DirectorySeparatorChar + name + ".lua";
                this.Interface.LoadFile(script);
            }

            if (this.Interface.IsSet(name)) {
                this.Interface.DoString("exec.scriptdir = [[" + this.ScriptDirectory(name) + "]]");
                return true;
            }

            return false;
        }
        private bool IsValidLuaScriptName(string command) {
            if (!Regex.IsMatch(command, "^[a-zA-Z0-9_]*$") ||
                command == "p" || command == "perseus" || command == "exec"
            ) {
                return false;
            }

            return true;
        }
        private string ScriptDirectory(string command) {
            return AppDomain.CurrentDomain.BaseDirectory + "scripts" + Path.DirectorySeparatorChar +
                command + Path.DirectorySeparatorChar;
        }

        #region IPluginLoader Members
        public void Load() {
            this.Interface = new Perseus.Scripting.Lua.Lua();
            this.Names = new List<string>();

            string dir = AppDomain.CurrentDomain.BaseDirectory + "scripts" + Path.DirectorySeparatorChar;
            if (Directory.Exists(dir)) {
                var luascripts = from s in Directory.GetFiles(dir)
                                 where Path.GetExtension(s) == ".lua"
                                 select Path.GetFileNameWithoutExtension(s);
                this.Names.AddRange(luascripts);
            }

            if (this.Names.Count > 0) {
                this.Interface.DoString("exec = {}");
                this.Interface.RegisterFunction("exec.display", this, "LuaDisplay");
            }
        }
        public void Unload() {
            this.Interface = null;
        }
        #endregion
    }
}
